/*
 * LauncherActivity.cpp
 *
 *  Created on: 2021年9月7日
 *      Author: vicent-PC
 */
#define LOG_TAG "LauncherActivity"
#include "LauncherActivity.h"

#include <HTTPClient.h>
#include <WiFi.h>
#include <stdio.h>
#include <time.h>

#include <string>


#include "./c3log.h"
#include "./screen_hal/DisplayCanvas.h"
#include "oled/ESP8266_and_ESP32_OLED_driver_for_SSD1306_displays/src/OLEDDisplayUi.h"
#include "oled/ESP8266_and_ESP32_OLED_driver_for_SSD1306_displays/src/SSD1306Wire.h"
#include "oled/oled_drv_intf.h"
#include <NtpTime.h>
#include <SystemServer.h>
#include <WifiManager.h>
#include <TimerActivity.h>

LauncherActivity * LauncherActivity::m_pInstance = nullptr;

LauncherActivity::LauncherActivity() {
}

LauncherActivity::~LauncherActivity() {
    if (mCanvas != nullptr) {
        delete mCanvas;
        mCanvas = nullptr;
    }
    if (mView != nullptr) {
        delete mView;
        mView = nullptr;
    }
}

void LauncherActivity::initDisplay() {
    OLEDDisplay* tempPen = DisplayCanvas::getInstance()->getPen();
    OLEDDisplayUi ui(tempPen);

    // clear dispaly
    tempPen->clear();
    tempPen->display();

    ui.setTargetFPS(30);
    // ui.setActiveSymbol(activeSymbole);
    // ui.setInactiveSymbol(inactiveSymbole);
    ui.setIndicatorPosition(BOTTOM);
    ui.setIndicatorDirection(LEFT_RIGHT);
    ui.setFrameAnimation(SLIDE_LEFT);
    // tempPen->display();
    ui.update();
}

void initCustomDisplay() {
    OLEDDisplay* tempPen = DisplayCanvas::getInstance()->getPen();
    tempPen->clear();
    tempPen->drawRect(0, 0, 128, 64);
    tempPen->setTextAlignment(TEXT_ALIGN_LEFT);
    tempPen->setFont(ArialMT_Plain_10);
}

void drawTitleStrength(int strength10 = -1) {
    OLEDDisplay* tempPen = DisplayCanvas::getInstance()->getPen();
    std::string str0 = "T";
    std::string str1 = "T.";
    std::string str2 = "T.r";
    std::string str3 = "T.rl";
    char* pStr = (char*)str0.c_str();
    if (strength10 <= 10 && strength10 >= 6) {
        pStr = (char*)str3.c_str();
    } else if (strength10 >= 3) {
        pStr = (char*)str2.c_str();
    } else if (strength10 >= 0) {
        pStr = (char*)str1.c_str();
    } else {
        pStr = (char*)str0.c_str();  // no signal
    }
    tempPen->drawString(128 - 16, 0, pStr);  // strength
}

void getLocalTime(char* timestr) {
    struct tm timeinfo;
    time_t rawtime;
    struct tm *info;

    time(&rawtime);

    info = localtime(&rawtime);
    // if (!getLocalTime(&timeinfo, 500)) {
    //     LOGW("Failed to obtain time, retry...");
    //     return;
    // }
    if (nullptr == info) {
        LOGW("Failed to obtain time, retry...");
        return;
    }

    snprintf(timestr, 16, "%d:%02d:%02d", info->tm_hour, info->tm_min,
             info->tm_sec);
}

void drawStatusBar() {
    OLEDDisplay* tempPen = DisplayCanvas::getInstance()->getPen();
    char timestr[16] = {0};
    // 1. Signal strength
    int strength = (100 + WifiManager::RSSI()) / 11;
    drawTitleStrength(strength);
    // 2. Time
    getLocalTime(timestr);
    tempPen->drawString(128 / 2 - strlen(timestr) * 6 / 2, 0, timestr);
}

void LauncherActivity::onDraw() {
    OLEDDisplay* tempPen = DisplayCanvas::getInstance()->getPen();
    tempPen->clear();
    tempPen->setFont(ArialMT_Plain_10);
    // draw status
    if (mWifiConnected) {
        drawStatusBar();
    }

    // draw IVP
    if (mInaAppInited) {
        mInaApp.pollIVP();
        float cur = 0.0, vol = 0.0, power = 0.0;
        mInaApp.getIVP(cur, vol, power);
        char tempStr[64] = {0};
        char ip[20] = {0};
        WifiManager::getInstance()->getIpStr(ip);
        tempPen->drawStringf(0, 30, tempStr, "%s", ip);
        tempPen->drawStringf(0, 40, tempStr, "%.01lfA %.01lfV %.01lfW", cur, vol, power);
    }
    tempPen->display();
}

void setupWifi(void * activity) {
    TRACE_B();
    LauncherActivity* pActivity = (LauncherActivity*)activity;
    for (int i = 0; i < 3; i++) {   // retry
        int ret = WifiManager::getInstance()->connect();
        if (ret < 0) {
            LOGE("wifi connect failed %d", i);
        } else {
            LOGI("wifi connect suc");
            pActivity->onWifiConnected();
            // obtainTimeFromhttp();
            break;
        }
    }
    vTaskDelete(NULL);
}

void LauncherActivity::setupWifiThread() {
    int ret = xTaskCreate(setupWifi,   /* Task function. */
                          "setupWifi", /* String with name of task. */
                          8192,         /* Stack size in bytes. */
                          this,  /* Parameter passed as input of the task */
                          0,     /* Priority of the task. */
                          NULL); /* Task handle. */
    if (ret != pdPASS) {
        LOGE("setupWifiThread start fail:%d", ret);
    }
}

void LauncherActivity::onCreate() {
    LOGI("%s E\n", __func__);
    int ret = 0;
    mView = new View();
    mCanvas = new Canvas();
    mView->add(mCanvas);
    setContentView(mView);

    // 1. initDisplay
    initCustomDisplay();

    OLEDDisplay* gPen = DisplayCanvas::getInstance()->getPen();
    gPen->drawString(2, 48, "connecting wifi...");
    gPen->display();

    // Start Web http server
    setupWifiThread();
    // 4. setup INA monitor
    ret = mInaApp.setup();
    if (0 == ret) {
        mInaAppInited = true;
        LOGI("%s mInaApp init suc\n", __func__);
    } else {
        LOGE("%s mInaApp init failed\n", __func__);
    }

    LOGI("%s X\n", __func__);
}

void LauncherActivity::onEvent() {
    LOGI("%s", __func__);
    SystemServer::getInstance()->startActivity(TimerActivity::getInstance());
}

void LauncherActivity::onWifiConnected() {
    LOGI("%s", __func__);
    mWifiConnected = true;
    // Start WebSocket Server
    WebSocketService* pWebSocketServer = WebSocketService::getInstance();
    pWebSocketServer->registerStreamSocket();
    pWebSocketServer->start();
    // 2. calibrate NTP Time
    obtain_timeThread(nullptr);
}
